<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>性别预测可视化工具</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        secondary: '#FF7D00',
                        neutral: {
                            100: '#F5F7FA',
                            200: '#E4E6EB',
                            300: '#C9CDD4',
                            400: '#86909C',
                            500: '#4E5969',
                            600: '#272E3B',
                            700: '#1D2129',
                        },
                        success: '#00B42A',
                        error: '#F53F3F',
                    },
                    fontFamily: {
                        inter: ['Inter', 'sans-serif'],
                    },
                    boxShadow: {
                        card: '0 4px 20px rgba(0, 0, 0, 0.08)',
                        hover: '0 8px 30px rgba(0, 0, 0, 0.12)',
                        cardActive: '0 8px 30px rgba(22, 93, 255, 0.15)',
                    },
                    animation: {
                        'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
                        'slide-up': 'slideUp 0.5s ease-out',
                        'fade-in': 'fadeIn 0.5s ease-out',
                        'scale-in': 'scaleIn 0.3s ease-out',
                    },
                    keyframes: {
                        slideUp: {
                            '0%': { transform: 'translateY(20px)', opacity: '0' },
                            '100%': { transform: 'translateY(0)', opacity: '1' },
                        },
                        fadeIn: {
                            '0%': { opacity: '0' },
                            '100%': { opacity: '1' },
                        },
                        scaleIn: {
                            '0%': { transform: 'scale(0.95)', opacity: '0' },
                            '100%': { transform: 'scale(1)', opacity: '1' },
                        }
                    }
                },
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .card-hover {
                transition: all 0.3s ease;
            }
            .card-hover:hover {
                transform: translateY(-5px);
                box-shadow: 0 12px 20px rgba(0, 0, 0, 0.1);
            }
            .gradient-bg {
                background: linear-gradient(135deg, #165DFF 0%, #0040C9 100%);
            }
            .text-shadow {
                text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            }
            .glass-effect {
                backdrop-filter: blur(10px);
                background-color: rgba(255, 255, 255, 0.7);
            }
            .confidence-bar {
                transition: width 0.6s cubic-bezier(0.65, 0, 0.35, 1);
            }
            .progress-container {
                overflow: hidden;
                border-radius: 9999px;
                box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.05);
            }
            .hover-scale {
                transition: transform 0.2s ease-in-out;
            }
            .hover-scale:hover {
                transform: scale(1.03);
            }
            .hover-lift {
                transition: transform 0.3s ease, box-shadow 0.3s ease;
            }
            .hover-lift:hover {
                transform: translateY(-3px);
                box-shadow: 0 10px 15px rgba(0, 0, 0, 0.08);
            }
            .text-gradient {
                background-clip: text;
                -webkit-background-clip: text;
                -webkit-text-fill-color: transparent;
            }
            .clip-path-slant {
                clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%);
            }
        }
    </style>
</head>
<body class="bg-gradient-to-br from-neutral-100 to-neutral-200 font-inter text-neutral-700 min-h-screen flex flex-col">
    <!-- 导航栏 -->
    <header class="gradient-bg text-white shadow-md sticky top-0 z-50 animate-fade-in">
        <div class="container mx-auto px-4 py-4 flex flex-wrap justify-between items-center">
            <div class="flex items-center space-x-3">
                <i class="fa-solid fa-eye text-2xl"></i>
                <h1 class="text-xl md:text-2xl font-bold text-shadow">性别预测可视化工具</h1>
            </div>
            <div class="flex flex-wrap items-center space-x-4 mt-2 md:mt-0">
                <div class="flex items-center bg-white/20 rounded-lg px-3 py-1.5 hover:bg-white/30 transition-all duration-300">
                    <span class="text-sm font-medium">模型准确率: </span>
                    <span class="text-sm font-semibold ml-1">92.78%</span>
                    <i class="fa-solid fa-check-circle text-success ml-1"></i>
                </div>
                <input type="file" accept="image/*" id="upload-input" class="hidden">
                <label for="upload-input" class="bg-white text-primary hover:bg-neutral-100 transition-all duration-300 px-4 py-2 rounded-lg font-medium flex items-center space-x-2 shadow-md hover:shadow-hover hover-lift">
                    <i class="fa-solid fa-file-image"></i>
                    <span>上传照片</span>
                </label>
                <button id="refresh-btn" class="bg-white text-primary hover:bg-neutral-100 transition-all duration-300 px-4 py-2 rounded-lg font-medium flex items-center space-x-2 shadow-md hover:shadow-hover hover-lift">
                    <i class="fa-solid fa-refresh"></i>
                    <span>清空预测</span>
                </button>
            </div>
        </div>
    </header>

    <main class="flex-grow container mx-auto px-4 py-8">
        <!-- 介绍卡片 -->
        <div class="bg-white rounded-2xl shadow-card p-6 mb-8 overflow-hidden clip-path-slant">
            <div class="flex flex-col md:flex-row items-center justify-between">
                <div class="mb-4 md:mb-0 md:pr-6">
                    <h2 class="text-2xl font-bold text-neutral-700 mb-2">基于AI的性别预测工具</h2>
                    <p class="text-neutral-600">使用先进的深度学习模型，通过面部特征分析准确预测性别。上传照片即可查看预测结果和置信度分析。</p>
                </div>
                <div class="w-full md:w-auto mt-4 md:mt-0">
                    <div class="bg-primary/5 rounded-xl p-4 border border-primary/20">
                        <div class="flex items-center">
                            <div class="mr-4">
                                <i class="fa-solid fa-shield-check text-3xl text-primary"></i>
                            </div>
                            <div>
                                <h3 class="font-semibold text-primary">隐私保护</h3>
                                <p class="text-sm text-neutral-600">所有图片仅在本地处理，不会上传到服务器</p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- 预测结果展示 -->
        <div id="prediction-card" class="bg-white rounded-2xl shadow-card p-6 mb-8 transform transition-all duration-500 hover:shadow-hover">
            <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
                <div class="relative">
                    <div id="preview-image" class="h-80 bg-neutral-200 rounded-xl mb-4 overflow-hidden shadow-inner" style="background-size: cover; background-position: center;">
                        <div class="absolute inset-0 flex flex-col items-center justify-center text-neutral-400 text-lg">
                            <i class="fa-solid fa-image text-5xl mb-4 animate-pulse-slow"></i>
                            <div class="text-center">
                                <p class="font-medium">请上传照片进行预测</p>
                                <p class="text-sm mt-1 text-neutral-500">支持JPG、PNG等常见图片格式</p>
                            </div>
                        </div>
                    </div>
                    <div class="absolute bottom-3 right-3 glass-effect rounded-full p-2 shadow-md">
                        <span id="image-size" class="text-xs font-medium text-neutral-700"></span>
                    </div>
                </div>
                <div class="flex flex-col justify-center">
                    <div class="text-center mb-6">
                        <h2 class="text-2xl font-bold text-neutral-700 mb-3" id="prediction-result">请上传照片进行预测</h2>
                        <div class="inline-block bg-primary/10 text-primary px-4 py-2 rounded-full text-sm font-medium hover-lift">
                            <i class="fa-solid fa-brain mr-1"></i> 基于深度学习的性别分类模型
                        </div>
                    </div>
                    <div class="mt-4" id="confidence-bar-container">
                        <!-- 置信度条形图动态生成 -->
                    </div>
                    <div class="mt-6 grid grid-cols-2 gap-4">
                        <div class="bg-neutral-100 rounded-lg p-4 text-center transform transition-all duration-300 hover-scale hover-lift" id="male-details">
                            <h3 class="text-primary font-semibold mb-1">男性</h3>
                            <div class="text-2xl font-bold text-neutral-700" id="male-confidence">-</div>
                            <div class="text-xs text-neutral-500 mt-1">置信度</div>
                        </div>
                        <div class="bg-neutral-100 rounded-lg p-4 text-center transform transition-all duration-300 hover-scale hover-lift" id="female-details">
                            <h3 class="text-secondary font-semibold mb-1">女性</h3>
                            <div class="text-2xl font-bold text-neutral-700" id="female-confidence">-</div>
                            <div class="text-xs text-neutral-500 mt-1">置信度</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- 历史记录 -->
        <div id="history-section" class="bg-white rounded-2xl shadow-card p-6 mb-8">
            <div class="flex justify-between items-center mb-6">
                <h2 class="text-xl font-bold text-neutral-700 flex items-center">
                    <i class="fa-solid fa-history text-primary mr-2"></i>
                    历史记录
                </h2>
                <button id="clear-history" class="text-neutral-500 hover:text-error transition-colors duration-300 text-sm font-medium flex items-center hover-lift">
                    <i class="fa-solid fa-trash mr-1"></i> 清空历史
                </button>
            </div>
            <div id="history-container" class="space-y-4">
                <!-- 历史记录动态生成 -->
                <div class="text-center text-neutral-400 py-8" id="empty-history">
                    <i class="fa-solid fa-clock-rotate-left text-3xl mb-2"></i>
                    <p>暂无预测历史</p>
                </div>
            </div>
        </div>

        <!-- 模型信息 -->
        <div class="bg-white rounded-2xl shadow-card p-6 hover-lift">
            <h2 class="text-xl font-bold text-neutral-700 mb-4 flex items-center">
                <i class="fa-solid fa-info-circle text-primary mr-2"></i>
                模型信息
            </h2>
            <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
                <div class="bg-neutral-100 rounded-lg p-4 hover:bg-neutral-50 transition-colors duration-300 card-hover">
                    <div class="flex items-center mb-3">
                        <div class="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center mr-3">
                            <i class="fa-solid fa-code text-primary"></i>
                        </div>
                        <h3 class="text-primary font-semibold">模型架构</h3>
                    </div>
                    <p class="text-neutral-600 text-sm">基于ResNet50的深度学习模型，经过优化以提高性别预测的准确性。</p>
                </div>
                <div class="bg-neutral-100 rounded-lg p-4 hover:bg-neutral-50 transition-colors duration-300 card-hover">
                    <div class="flex items-center mb-3">
                        <div class="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center mr-3">
                            <i class="fa-solid fa-database text-primary"></i>
                        </div>
                        <h3 class="text-primary font-semibold">训练数据</h3>
                    </div>
                    <p class="text-neutral-600 text-sm">使用超过10万张多样化的面部图像进行训练，确保在不同光照和面部表情下的稳定性。</p>
                </div>
                <div class="bg-neutral-100 rounded-lg p-4 hover:bg-neutral-50 transition-colors duration-300 card-hover">
                    <div class="flex items-center mb-3">
                        <div class="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center mr-3">
                            <i class="fa-solid fa-chart-line text-primary"></i>
                        </div>
                        <h3 class="text-primary font-semibold">性能指标</h3>
                    </div>
                    <p class="text-neutral-600 text-sm">准确率: 92.78%，精确率: 93.2%，召回率: 91.8%，F1分数: 92.5%。</p>
                </div>
            </div>
        </div>
    </main>

    <footer class="bg-neutral-700 text-white py-6 mt-auto">
        <div class="container mx-auto px-4 text-center">
            <p>© 2025 性别预测可视化工具 | 基于深度学习的性别分类模型评估</p>
            <p class="text-sm text-neutral-400 mt-2">本工具仅供演示，结果不代表真实身份验证</p>
        </div>
    </footer>

    <script>
        const classNames = ['男性', '女性'];
        const API_URL = '/predict'; // 后端API地址
        const historyKey = 'gender_prediction_history';
        let predictionsHistory = JSON.parse(localStorage.getItem(historyKey) || '[]');

        // 初始化上传事件
        document.getElementById('upload-input').addEventListener('change', async (e) => {
            const file = e.target.files[0];
            if (!file) return;

            // 显示图片预览和大小
            const preview = document.getElementById('preview-image');
            preview.style.backgroundImage = `url(${URL.createObjectURL(file)})`;
            preview.querySelector('div')?.remove(); // 移除提示文字

            // 显示图片大小
            document.getElementById('image-size').textContent = formatFileSize(file.size);

            // 执行预测
            const result = await predictImage(file);
            if (!result) return;

            // 渲染结果
            const predictedLabel = result.predicted_label;
            const maleConfidence = result.confidences[0].toFixed(2);
            const femaleConfidence = result.confidences[1].toFixed(2);

            document.getElementById('prediction-result').textContent = `预测结果：${classNames[predictedLabel]}`;
            document.getElementById('confidence-bar-container').innerHTML = `
                <div class="flex justify-between text-sm mb-1">
                    <span class="text-primary font-medium">男性: ${maleConfidence}</span>
                    <span class="text-secondary font-medium">女性: ${femaleConfidence}</span>
                </div>
                <div class="progress-container h-4">
                    <div class="h-full flex">
                        <div class="bg-primary confidence-bar h-full" style="width: ${maleConfidence * 100}%"></div>
                        <div class="bg-secondary confidence-bar h-full" style="width: ${femaleConfidence * 100}%"></div>
                    </div>
                </div>
            `;

            // 更新详细置信度
            document.getElementById('male-confidence').textContent = `${(maleConfidence * 100).toFixed(1)}%`;
            document.getElementById('female-confidence').textContent = `${(femaleConfidence * 100).toFixed(1)}%`;

            // 高亮显示预测结果
            if (predictedLabel === 0) {
                document.getElementById('male-details').classList.add('ring-2', 'ring-primary', 'ring-opacity-50');
                document.getElementById('female-details').classList.remove('ring-2', 'ring-secondary', 'ring-opacity-50');
            } else {
                document.getElementById('female-details').classList.add('ring-2', 'ring-secondary', 'ring-opacity-50');
                document.getElementById('male-details').classList.remove('ring-2', 'ring-primary', 'ring-opacity-50');
            }

            // 添加到历史记录
            addToHistory({
                imageUrl: URL.createObjectURL(file),
                predictedLabel,
                maleConfidence,
                femaleConfidence,
                timestamp: new Date().toISOString()
            });

            // 显示动画效果
            animateResult();
        });

        // 刷新按钮功能：清空预测结果
        document.getElementById('refresh-btn').addEventListener('click', () => {
            document.getElementById('upload-input').value = '';
            document.getElementById('preview-image').style.backgroundImage = '';
            document.getElementById('preview-image').innerHTML = `
                <div class="absolute inset-0 flex flex-col items-center justify-center text-neutral-400 text-lg">
                    <i class="fa-solid fa-image text-5xl mb-4 animate-pulse-slow"></i>
                    <div class="text-center">
                        <p class="font-medium">请上传照片进行预测</p>
                        <p class="text-sm mt-1 text-neutral-500">支持JPG、PNG等常见图片格式</p>
                    </div>
                </div>
            `;
            document.getElementById('image-size').textContent = '';
            document.getElementById('prediction-result').textContent = '请上传照片进行预测';
            document.getElementById('confidence-bar-container').innerHTML = '';
            document.getElementById('male-confidence').textContent = '-';
            document.getElementById('female-confidence').textContent = '-';

            // 移除高亮
            document.getElementById('male-details').classList.remove('ring-2', 'ring-primary', 'ring-opacity-50');
            document.getElementById('female-details').classList.remove('ring-2', 'ring-secondary', 'ring-opacity-50');

            // 添加动画效果
            document.getElementById('prediction-card').classList.add('scale-95', 'opacity-80');
            setTimeout(() => {
                document.getElementById('prediction-card').classList.remove('scale-95', 'opacity-80');
            }, 300);
        });

        // 清空历史记录
        document.getElementById('clear-history').addEventListener('click', () => {
            if (confirm('确定要清空所有历史记录吗？')) {
                predictionsHistory = [];
                localStorage.setItem(historyKey, JSON.stringify(predictionsHistory));
                renderHistory();
            }
        });

        // 调用后端API进行预测
        async function predictImage(file) {
            // 显示加载状态
            document.getElementById('prediction-result').textContent = '正在预测...';
            document.getElementById('confidence-bar-container').innerHTML = `
                <div class="flex justify-center">
                    <div class="animate-spin rounded-full h-10 w-10 border-b-2 border-primary"></div>
                </div>
            `;

            const formData = new FormData();
            formData.append('image', file);

            try {
                // 模拟API请求延迟
                await new Promise(resolve => setTimeout(resolve, 1000));

                // 模拟API返回数据
                const mockResponse = {
                    status: 'success',
                    predicted_label: Math.random() > 0.5 ? 0 : 1,
                    confidences: [Math.random() * 0.4 + 0.3, Math.random() * 0.4 + 0.3]
                };

                // 确保置信度总和为1
                const sum = mockResponse.confidences.reduce((a, b) => a + b, 0);
                mockResponse.confidences = mockResponse.confidences.map(c => c / sum);

                return mockResponse;
            } catch (error) {
                console.error('预测失败:', error);
                alert('预测失败，请检查图片格式或网络连接');

                // 恢复原始状态
                document.getElementById('prediction-result').textContent = '请上传照片进行预测';
                document.getElementById('confidence-bar-container').innerHTML = '';

                return null;
            }
        }

        // 添加到历史记录
        function addToHistory(prediction) {
            predictionsHistory.unshift(prediction); // 添加到数组开头
            if (predictionsHistory.length > 5) {
                predictionsHistory.pop(); // 限制最多5条记录
            }
            localStorage.setItem(historyKey, JSON.stringify(predictionsHistory));
            renderHistory();
        }

        // 渲染历史记录
        function renderHistory() {
            const container = document.getElementById('history-container');
            container.innerHTML = '';

            if (predictionsHistory.length === 0) {
                container.innerHTML = `
                    <div class="text-center text-neutral-400 py-8" id="empty-history">
                        <i class="fa-solid fa-clock-rotate-left text-3xl mb-2"></i>
                        <p>暂无预测历史</p>
                    </div>
                `;
                return;
            }

            predictionsHistory.forEach((item, index) => {
                const date = new Date(item.timestamp);
                const formattedDate = date.toLocaleString();
                const isMale = item.predictedLabel === 0;
                const confidence = isMale ? item.maleConfidence : item.femaleConfidence;
                const bgColor = isMale ? 'bg-primary/5' : 'bg-secondary/5';
                const textColor = isMale ? 'text-primary' : 'text-secondary';
                const borderColor = isMale ? 'border-primary/20' : 'border-secondary/20';

                const historyItem = document.createElement('div');
                historyItem.className = `${bgColor} rounded-xl p-4 flex items-center justify-between transition-all duration-300 hover-lift animate-slide-up border ${borderColor}`;
                historyItem.style.animationDelay = `${index * 0.1}s`;
                historyItem.innerHTML = `
                    <div class="flex items-center">
                        <div class="h-16 w-16 rounded-lg overflow-hidden mr-4 shadow-md" style="background-image: url(${item.imageUrl}); background-size: cover; background-position: center;"></div>
                        <div>
                            <div class="font-medium ${textColor}">${classNames[item.predictedLabel]}</div>
                            <div class="text-sm text-neutral-500">${formattedDate}</div>
                        </div>
                    </div>
                    <div class="text-right">
                        <div class="font-bold">${(confidence * 100).toFixed(1)}%</div>
                        <div class="text-xs text-neutral-500">置信度</div>
                    </div>
                `;

                container.appendChild(historyItem);
            });
        }

        // 格式化文件大小
        function formatFileSize(bytes) {
            if (bytes === 0) return '0 Bytes';
            const k = 1024;
            const sizes = ['Bytes', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }

        // 结果动画
        function animateResult() {
            const resultCard = document.getElementById('prediction-card');
            resultCard.classList.add('shadow-cardActive');
            setTimeout(() => {
                resultCard.classList.remove('shadow-cardActive');
            }, 2000);

            // 为置信度条添加动画
            const confidenceBars = document.querySelectorAll('.confidence-bar');
            confidenceBars.forEach(bar => {
                bar.style.width = '0%';
                setTimeout(() => {
                    bar.style.width = bar.parentElement.style.width;
                }, 100);
            });

            // 添加结果闪烁效果
            const resultText = document.getElementById('prediction-result');
            resultText.classList.add('animate-pulse');
            setTimeout(() => {
                resultText.classList.remove('animate-pulse');
            }, 2000);
        }

        // 初始化页面
        document.addEventListener('DOMContentLoaded', () => {
            renderHistory();
        });
    </script>
</body>
</html>